package workflow;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;

import model.Software;
import workerUIs.SpecificationStepFrame;
import workerUIs.StepFrame;
import workerUIs.TestFrame;
import workers.ArchitectureStepWorker;
import workers.ImplementationStepWorker;
import workers.IntegrationStepWorker;
import workers.ReleaseStepWorker;
import workers.RepairStepWorker;
import workers.SpecificationStepWorker;
import workers.TestStepWorker;
import workers.UIStepWorker;

/**
 * SoftwareDevelopmentWorkflow class. 
 * Represents the main class in the Application.
 * 
 * @author Mark Czotter
 * @author Miklos Szennai
 * 
 */
public class SoftwareDevelopmentWorkflow {
	
	private Logger logger = Logger.getLogger(SoftwareDevelopmentWorkflow.class.getCanonicalName());
	
	public SoftwareDevelopmentWorkflow() {
	}
	
	/**
	 * Starts the development immediately.
	 */
	public void startDevelopment() {
		try {
			// create all blockingQueues
			final BlockingQueue<Software> archiInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> implInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> uiInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> implOutputintegrationInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> uiOutputIntegrationInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> testInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> repairStepInputQueue = new ArrayBlockingQueue<Software>(5);
			final BlockingQueue<Software> releaseStepInputQueue = new ArrayBlockingQueue<Software>(5);
			// create all frames backwards from release to spec, and add actionListeners to buttons
			final StepFrame releaseFrame = new StepFrame("Step5: Release");
			releaseFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new ReleaseStepWorker(releaseFrame, releaseStepInputQueue).execute();
				}
			});
			final StepFrame repairFrame = new StepFrame("Step4e: Repair");
			repairFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					new RepairStepWorker(repairFrame, repairStepInputQueue, releaseStepInputQueue, releaseFrame).execute();
				}
			});
			final TestFrame testFrame = new TestFrame("If block: Testing");
			testFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent arg0) {
					new TestStepWorker(testFrame, testInputQueue, repairStepInputQueue, releaseStepInputQueue, repairFrame, releaseFrame).execute();					
				}
			});
			final StepFrame integrationFrame = new StepFrame("Step4: Integration");
			integrationFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new IntegrationStepWorker(integrationFrame, implOutputintegrationInputQueue, uiOutputIntegrationInputQueue, testInputQueue, testFrame).execute();				
				}
			});
			final StepFrame uiImplFrame = new StepFrame("Step3b: UI Impl");
			uiImplFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new UIStepWorker(uiImplFrame, uiInputQueue, uiOutputIntegrationInputQueue, integrationFrame).execute();				
				}
			});
			final StepFrame implementationFrame = new StepFrame("Step3a: Implementation");
			implementationFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new ImplementationStepWorker(implementationFrame, implInputQueue, implOutputintegrationInputQueue, integrationFrame).execute();				
				}
			});
			final StepFrame architectureFrame = new StepFrame("Step2: Architecure Design");
			architectureFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new ArchitectureStepWorker(architectureFrame, archiInputQueue, implInputQueue, uiInputQueue, implementationFrame, uiImplFrame).execute();				
				}
			});
			final SpecificationStepFrame specFrame = new SpecificationStepFrame("Step1: Specification", true);
			specFrame.getNextButton().addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					new SpecificationStepWorker(specFrame, archiInputQueue, architectureFrame).execute();				
				}
			});
		} catch (Exception e) {
			logger.log(Level.SEVERE, "Error during initialization: ", e);
//			e.printStackTrace();
		}
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		new SoftwareDevelopmentWorkflow().startDevelopment();
	}

}
